package com.zou.practice.sort;

import com.alibaba.fastjson.JSON;

/**
 * @author zouyaowen
 * @date 2020-09-14
 */
public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {13, 3, 2, 9, 8, 7, 11};
        System.out.println(JSON.toJSONString(arr));
        heapSort(arr);
        System.out.println(JSON.toJSONString(arr));
    }

    private static void heapSort(int[] arr) {
        buildHeap(arr);
    }

    /**
     * 使用数组构建二叉堆
     *
     * @param arr 待排序数组
     */
    private static void buildHeap(int[] arr) {
        // 从最后一个非叶子节点开始，依次下沉调整
        int parent = (arr.length >> 1) - 1;
        for (int i = parent; i >= 0; i--) {
            downAdjust(arr, i, arr.length);
        }

    }

    /**
     * 下沉调整
     *
     * @param arr         待排序数组
     * @param parentIndex 待调整父节点
     * @param length      数组长度
     */
    private static void downAdjust(int[] arr, int parentIndex, int length) {
        // temp保存父节点值，用于最后的赋值
        int temp = arr[parentIndex];
        int childIndex = 2 * parentIndex + 1;
        while (childIndex < length) {
            // 如果有右孩子，且右孩子小于左孩子的值，则定位到右孩子
            if (childIndex + 1 < length && arr[childIndex + 1] < arr[childIndex]) {
                childIndex++;
            }
            // 如果父节点小于任何一个孩子的值，直接跳出
            if (temp <= arr[childIndex]) {
                break;
            }
            // 无需真正交换，单向赋值即可
            arr[parentIndex] = arr[childIndex];
            parentIndex = childIndex;
            childIndex = 2 * childIndex + 1;
        }
        arr[parentIndex] = temp;
    }

    /**
     * 上浮调整
     *
     * @param array 待调整数组
     */
    public static void upAdjust(int[] array) {
        int childIndex = array.length - 1;
        int parentIndex = (childIndex - 1) / 2;
        // temp保存插入的叶子节点值，用于最后的赋值
        int temp = array[childIndex];
        while (childIndex > 0 && temp < array[parentIndex]) {
            //无需真正交换，单向赋值即可
            array[childIndex] = array[parentIndex];
            childIndex = parentIndex;
            parentIndex = (parentIndex - 1) / 2;
        }
        array[childIndex] = temp;
    }

}
